home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / mach / ds3100.md / socket.c < prev    next >
C/C++ Source or Header  |  1991-07-26  |  35KB  |  1,305 lines

  1. /* 
  2.  * socket.c --
  3.  *
  4.  *    Routines to emulate 4.3 BSD socket-related system calls for IPC
  5.  *    using the Internet protocol suite. The routines make calls to 
  6.  *    the Sprite Internet Server using Sprite system calls.
  7.  *
  8.  * Copyright 1987 Regents of the University of California
  9.  * All rights reserved.
  10.  */
  11.  
  12. #ifndef lint
  13. static char rcsid[] = "$Header: /sprite/src/kernel/mach/ds3100.md/RCS/socket.c,v 9.2 91/07/26 17:02:36 shirriff Exp $ SPRITE (Berkeley)";
  14. #endif not lint
  15.  
  16. #include "sprite.h"
  17. #include "user/bit.h"
  18. #include "user/dev/net.h"
  19. #include "user/fs.h"
  20. #include "user/inet.h"
  21. #include "user/status.h"
  22. #include "user/stdlib.h"
  23. #include "user/sys.h"
  24. #include "user/sys/types.h"
  25. #include "user/sys/socket.h"
  26. #include "user/sys/uio.h"
  27. #include "user/netinet/in.h"
  28. #include "machInt.h"
  29. #include "mach.h"
  30.  
  31. #include "compatInt.h"
  32.  
  33. extern Mach_State    *machCurStatePtr;
  34.  
  35. #if 0
  36. static ReturnStatus Wait _ARGS_((int socketID, Boolean readSelect, Time *timeOutPtr));
  37. #endif
  38.  
  39. #ifdef DEBUG
  40. #  define    DebugMsg(status, string)     printf("%x: %s\n", status, string)
  41. #else
  42. #  define    DebugMsg(status, string)    ;
  43. #endif
  44.  
  45. static Boolean    gotHostName = FALSE;
  46. static char     streamDevice[100];
  47. static char     dgramDevice[100];
  48. static char     rawDevice[100];
  49.  
  50.  
  51. /*
  52.  *----------------------------------------------------------------------
  53.  *
  54.  * accept --
  55.  *
  56.  *    Accept a stream connection request. This call will create a new
  57.  *    connection to the Inet server upon notification that a remote
  58.  *    connection request is pending.
  59.  *
  60.  *    If the socket is non-blocking and no remote connection requests are
  61.  *    pending, EWOULDBLOCK is returned. If the socket is blockable,
  62.  *    this routine will wait until a remote connection request arrives.
  63.  *
  64.  * Results:
  65.  *    If > 0, the stream ID of the new connection.
  66.  *    If UNIX_ERROR, errno = 
  67.  *    EINVAL        - Bad size for *namePtr.
  68.  *    EWOULDBLOCK    - Non pending requests.
  69.  *
  70.  * Side effects:
  71.  *    A new stream is created.
  72.  *
  73.  *----------------------------------------------------------------------
  74.  */
  75.  
  76. ReturnStatus
  77. MachUNIXAccept(socketID, addrPtr, addrLenPtr)
  78.     int            socketID;    /* Socket to listen on. */
  79.     struct sockaddr_in    *addrPtr;    /* Address of newly-accepted 
  80.                      * connection. (out) */
  81.     int            *addrLenPtr;    /* Size of *addrPtr. (in/out) */
  82. {
  83.     ReturnStatus    status;
  84.     int            newSocket;
  85.     int            addrLen;
  86.  
  87.     Address        usp;
  88.     int            *newSocketPtr;
  89.     ClientData        *acceptTokenPtr;
  90.     struct sockaddr_in    addr;
  91.  
  92.     usp = (Address)machCurStatePtr->userState.regState.regs[SP];
  93.     newSocketPtr = (int *)(usp - sizeof(int));
  94.     acceptTokenPtr = (ClientData *) (usp - sizeof(int) - sizeof(ClientData));
  95.  
  96.     if (addrLenPtr == (int *) NULL) {
  97.     addrLen = 0;
  98.     addrPtr = (struct sockaddr_in *) NULL;
  99.     } else {
  100.     /*
  101.      * We deal with just Internet sockets.
  102.      */
  103.     status = Vm_CopyIn(sizeof(addrLen), (Address)addrLenPtr, 
  104.                (Address)&addrLen);
  105.     if (status != SUCCESS) {
  106.         return(status);
  107.     }
  108.     if (addrLen != sizeof(struct sockaddr_in)) {
  109.         return(SYS_INVALID_ARG);
  110.     }
  111.     }
  112.  
  113.  
  114.     /*
  115.      * Tell the Inet server to accept connections on the socket.  If a
  116.      * connection is made, a token is returned that is used to convert the
  117.      * connection into a new socket.  If no connections are currently
  118.      * available and the socket is non-blocking, FS_WOULD_BLOCK is
  119.      * returned. If the socket is blockable, the ioctl returns
  120.      * NET_NO_CONNECTS so and Wait() must be used to wait for a
  121.      * connection.
  122.      */
  123.  
  124.     status = Fs_IOControlStub(socketID, IOC_NET_ACCEPT_CONN_1, 
  125.                 0, (Address) NULL, 
  126.             sizeof(ClientData), (Address) acceptTokenPtr);
  127.  
  128.     switch (status) {
  129.     case SUCCESS:
  130.         break;
  131.  
  132.     case FS_WOULD_BLOCK:
  133.         return(FS_WOULD_BLOCK);
  134.  
  135.         case NET_NO_CONNECTS:
  136.         /*
  137.          * Wait for the server to tell us that a request has arrived.
  138.          */
  139. #if 0
  140.         (void) Wait(socketID, TRUE, (Time *) NULL);
  141. #endif
  142.  
  143.         /*
  144.          * There's a pending connection so retry the ioctl.
  145.          */
  146.         status = Fs_IOControlStub(socketID, IOC_NET_ACCEPT_CONN_1, 
  147.                 0, (Address) NULL, 
  148.             sizeof(ClientData), (Address) acceptTokenPtr);
  149.         if (status != SUCCESS) {
  150.         DebugMsg(status, "accept (ioctl 1b)");
  151.         return(status);
  152.         }
  153.         break;
  154.  
  155.     default:
  156.         DebugMsg(status, "accept (ioctl 1a)");
  157.         return(status);
  158.     } 
  159.  
  160.  
  161.     /*
  162.      * Create the new socket. This socket will be converted into the new
  163.      * connection.
  164.      */
  165.  
  166.     status = Fs_OpenStub(streamDevice, FS_READ|FS_WRITE, 0666, newSocketPtr);
  167.     if (status != SUCCESS) {
  168.     DebugMsg(status, "accept (open)");
  169.     return(status);
  170.     }
  171.     (void)Vm_CopyIn(sizeof(newSocket), (Address)newSocketPtr, 
  172.             (Address)&newSocket);
  173.  
  174.     /*
  175.      * Make the new socket have the same characteristics as the
  176.      * connection socket. Also, find out who we are connected to.
  177.      */
  178.     status = Fs_IOControlStub(newSocket, IOC_NET_ACCEPT_CONN_2, 
  179.             sizeof(ClientData), (Address) acceptTokenPtr, 
  180.             addrLen, (Address) addrPtr);
  181.  
  182.     if (status != SUCCESS) {
  183.     DebugMsg(status, "accept (ioctl 2)");
  184.     return(status);
  185.     }
  186.     if (addrLen > 0) {
  187.     (void)Vm_CopyIn(addrLen, (Address)addrPtr, (Address)&addr);
  188.     addr.sin_family = AF_INET;
  189.     (void)Vm_CopyOut(addrLen, (Address)&addr, (Address)addrPtr);
  190.     }
  191.     machCurStatePtr->userState.unixRetVal = newSocket;
  192.  
  193.     return(SUCCESS);
  194. }
  195.  
  196. /*
  197.  *----------------------------------------------------------------------
  198.  *
  199.  * bind --
  200.  *
  201.  *    Assigns a local <address,port> tuple to a socket that does 
  202.  *    not have one.
  203.  *
  204.  * Results:
  205.  *    If 0        - Successful.
  206.  *    If UNIX_ERROR, then errno = 
  207.  *    EINVAL        - Bad size for *namePtr, already bound to an address.
  208.  *    EADDRINUSE    - The address is already in use.
  209.  *    EADDRNOTAVAIL    - The address is not valid for this host.
  210.  *
  211.  * Side effects:
  212.  *    The socket local address is set.
  213.  *
  214.  *----------------------------------------------------------------------
  215.  */
  216.  
  217. ReturnStatus
  218. MachUNIXBind(socketID, namePtr, nameLen)
  219.     int            socketID;    /* Stream ID of unnamed socket. */
  220.     struct sockaddr    *namePtr;    /* Local address,port for this socket.*/
  221.     int            nameLen;    /* Size of *namePtr. */
  222. {
  223.     ReturnStatus    status;
  224.  
  225.     if (nameLen != sizeof(struct sockaddr_in)) {
  226.     return(SYS_INVALID_ARG);
  227.     }
  228.  
  229.     status = Fs_IOControlStub(socketID, IOC_NET_SET_LOCAL_ADDR, 
  230.             nameLen, (Address) namePtr, 
  231.             0, (Address) NULL);
  232.     if (status != SUCCESS) {
  233.     DebugMsg(status, "bind");
  234.     }
  235.     return(status);
  236. }
  237.  
  238. /*
  239.  *----------------------------------------------------------------------
  240.  *
  241.  * connect --
  242.  *
  243.  *    For a stream socket, create a connection to a remote host.
  244.  *    For a datagram socket, only receive datagrams from this remote 
  245.  *    address.
  246.  *
  247.  * Results:
  248.  *    If 0        - Successful.
  249.  *    If UNIX_ERROR, then errno = 
  250.  *    EINVAL        - Bad size for *namePtr,
  251.  *    EADDRINUSE    - The address is already in use.
  252.  *    EADDRNOTAVAIL    - The address is not valid for this host.
  253.  *    EISCONN        - The socket is already connected.
  254.  *    ETIMEDOUT    - The connection request timed-out.
  255.  *    ECONNREFUSED    - The remote host refused the connection.
  256.  *    ENETUNREACH    - The network isn't reachable from this host.
  257.  *    EWOULDBLOCK    - If non-blocking, the connection can't be completed
  258.  *                immediately.
  259.  *    EFAULT        - Invalid argument to the ioctl.
  260.  *
  261.  * Side effects:
  262.  *    A local address for the socket is given if it did not have one 
  263.  *    already.
  264.  *
  265.  *----------------------------------------------------------------------
  266.  */
  267.  
  268. ReturnStatus
  269. MachUNIXConnect(socketID, namePtr, nameLen)
  270.     int            socketID;    /* Stream ID of socket. */
  271.     struct sockaddr    *namePtr;    /* Remote address,port to connect to.*/
  272.     int            nameLen;    /* Size of *namePtr. */
  273. {
  274.     ReturnStatus    status;
  275.  
  276.     if (nameLen != sizeof(struct sockaddr_in)) {
  277.     return(SYS_INVALID_ARG);
  278.     }
  279.  
  280.     status = Fs_IOControlStub(socketID, IOC_NET_CONNECT,
  281.                   nameLen, (Address) namePtr, 
  282.                   0, (Address) NULL);
  283.  
  284.     if (status == FS_WOULD_BLOCK) {
  285.     int flags = 0;
  286.     Address    usp;
  287.     int *intPtr;
  288.     int optionsArray[2];
  289.     int *userOptionsArray;
  290.  
  291.     usp = (Address)machCurStatePtr->userState.regState.regs[SP];
  292.     intPtr = (int *)(usp - sizeof(int));
  293.     userOptionsArray = 
  294.             (int *)(machCurStatePtr->userState.regState.regs[SP] - 
  295.             3 * sizeof(int));
  296.  
  297.     /*
  298.      * The connection didn't immediately complete, so wait if
  299.      * we're blocking or return EWOULDBLOCK if we're non-blocking.
  300.      */
  301.     status = Fs_IOControlStub(socketID, IOC_GET_FLAGS, 
  302.             0, (Address) NULL,
  303.             sizeof(flags), (Address) intPtr);
  304.  
  305.     if (status != SUCCESS) {
  306.         DebugMsg(status, "connect (ioctl)");
  307.         return(status);
  308.     }
  309.     (void)Vm_CopyIn(sizeof(flags), (Address)intPtr, (Address)&flags);
  310.  
  311.     if (flags & IOC_NON_BLOCKING) {
  312.         return(FS_WOULD_BLOCK);
  313.     } 
  314.  
  315. #if 0
  316.     status = Wait(socketID, FALSE, &time_OneMinute);
  317. #endif
  318.  
  319.     if (status == FS_TIMEOUT) {
  320.         DebugMsg(status, "connect (select)");
  321.         return(status);
  322.     }
  323.  
  324.     /*
  325.      * See if the connection successfully completed.
  326.      */
  327.     optionsArray[0] = SOL_SOCKET;
  328.     optionsArray[1] = SO_ERROR;
  329.     status = Vm_CopyOut(2 * sizeof(int), (Address)optionsArray, 
  330.                 (Address)userOptionsArray);
  331.     if (status != SUCCESS) {
  332.         return(status);
  333.     }
  334.     status = Fs_IOControlStub(socketID, IOC_NET_GET_OPTION,
  335.             sizeof(optionsArray), (Address) userOptionsArray, 
  336.             sizeof(int), (Address) intPtr);
  337.     if (status != SUCCESS) {
  338.         DebugMsg(status, "connect (getsockopt)");
  339.         return(status);
  340.     }
  341.     (void)Vm_CopyIn(sizeof(int), (Address)intPtr, (Address)&status);
  342.     } else if (status != SUCCESS) {
  343.     DebugMsg(status, "connect");
  344.     }
  345.     return(status);
  346. }
  347.  
  348. /*
  349.  *----------------------------------------------------------------------
  350.  *
  351.  * getpeername --
  352.  *
  353.  *    Find out the remote address that this socket is connected to.
  354.  *
  355.  * Results:
  356.  *    If 0        - Successful.
  357.  *    If UNIX_ERROR, then errno = 
  358.  *    EINVAL        - Bad size for *namePtr.
  359.  *    ENOTCONN    - The socket is not connected.
  360.  *    EFAULT        - Invalid argument to the ioctl.
  361.  *
  362.  * Side effects:
  363.  *    None.
  364.  *
  365.  *----------------------------------------------------------------------
  366.  */
  367.  
  368. ReturnStatus
  369. MachUNIXGetPeerName(socketID, namePtr, nameLenPtr)
  370.     int            socketID;    /* Stream ID of socket connected to 
  371.                      * remote peer. */
  372.     struct sockaddr    *namePtr;    /* Upon return, <addr,port> for 
  373.                      * remote peer. */
  374.     int            *nameLenPtr;    /* Size of *namePtr. (in/out) */
  375. {
  376.     ReturnStatus    status;
  377.     int            nameLen;
  378.  
  379.     if (nameLenPtr == (int *) NULL) {
  380.     return(SYS_INVALID_ARG);
  381.     }
  382.     status = Vm_CopyIn(sizeof(int), (Address)nameLenPtr, (Address)&nameLen);
  383.     if (status != SUCCESS) {
  384.     return(status);
  385.     }
  386.     if (nameLen < sizeof(struct sockaddr_in)) {
  387.     return(SYS_INVALID_ARG);
  388.     }
  389.     if (nameLen > sizeof(struct sockaddr_in)) {
  390.     nameLen = sizeof(struct sockaddr_in);
  391.     status = Vm_CopyOut(sizeof(int),(Address)&nameLen, (Address)nameLenPtr);
  392.     if (status != SUCCESS) {
  393.         return(status);
  394.     }
  395.     }
  396.  
  397.     status = Fs_IOControlStub(socketID, IOC_NET_GET_REMOTE_ADDR, 
  398.             0, (Address) NULL, 
  399.             nameLen, (Address) namePtr);
  400.     if (status != SUCCESS) {
  401.     DebugMsg(status, "getpeername");
  402.     }
  403.     return(status);
  404. }
  405.  
  406.  
  407. /*
  408.  *----------------------------------------------------------------------
  409.  *
  410.  * getsockname --
  411.  *
  412.  *    Find out the local address for this socket, which was
  413.  *    set with the bind routine or by the connect routine.
  414.  *
  415.  * Results:
  416.  *    If 0        - Successful.
  417.  *    If UNIX_ERROR, then errno = 
  418.  *    EINVAL        - Bad size for *namePtr.
  419.  *    EFAULT        - Invalid argument to the ioctl.
  420.  *
  421.  * Side effects:
  422.  *    None.
  423.  *
  424.  *----------------------------------------------------------------------
  425.  */
  426.  
  427. ReturnStatus
  428. MachUNIXGetSockName(socketID, namePtr, nameLenPtr)
  429.     int            socketID;    /* Stream ID of socket to get name of.*/
  430.     struct sockaddr    *namePtr;    /* Upon return, current <addr,port> for
  431.                      * this socket. */
  432.     int            *nameLenPtr;    /* Size of *namePtr. (in/out) */
  433. {
  434.     ReturnStatus    status;
  435.     int            nameLen;
  436.  
  437.     if (nameLenPtr == (int *) NULL) {
  438.     return(SYS_INVALID_ARG);
  439.     }
  440.     status = Vm_CopyIn(sizeof(int), (Address)nameLenPtr, (Address)&nameLen);
  441.     if (status != SUCCESS) {
  442.     return(status);
  443.     }
  444.     if (nameLen < sizeof(struct sockaddr_in)) {
  445.     return(SYS_INVALID_ARG);
  446.     }
  447.     if (nameLen > sizeof(struct sockaddr_in)) {
  448.     nameLen = sizeof(struct sockaddr_in);
  449.     status = Vm_CopyOut(sizeof(int),(Address)&nameLen, (Address)nameLenPtr);
  450.     if (status != SUCCESS) {
  451.         return(status);
  452.     }
  453.     }
  454.  
  455.     status = Fs_IOControlStub(socketID, IOC_NET_GET_LOCAL_ADDR, 
  456.                   0, (Address) NULL, 
  457.                   nameLen, (Address) namePtr);
  458.  
  459.     if (status != SUCCESS) {
  460.     DebugMsg(status, "getsockname");
  461.     }
  462.     return(status);
  463. }
  464.  
  465. /*
  466.  *----------------------------------------------------------------------
  467.  *
  468.  * getsockopt --
  469.  *
  470.  *    Get the value for a socket option.
  471.  *
  472.  * Results:
  473.  *    If 0        - Successful.
  474.  *    If UNIX_ERROR, then errno = 
  475.  *    EFAULT        - Invalid argument to the ioctl.
  476.  *
  477.  * Side effects:
  478.  *    None.
  479.  *
  480.  *----------------------------------------------------------------------
  481.  */
  482.  
  483. ReturnStatus
  484. MachUNIXGetSockOpt(socketID, level, optName, optVal, optLenPtr)
  485.     int        socketID;    /* Stream ID of socket to get options on. */
  486.     int        level;        /* Socket or protocol level to get the option.*/
  487.     int        optName;    /* Type of option to get. */
  488.     char    *optVal;    /* Address of buffer to store the result. */
  489.     int        *optLenPtr;    /* In: Size of *optVal, out: # of bytes stored
  490.                  * in *optVal. */
  491. {
  492.     ReturnStatus    status;
  493.     int            optionsArray[2];
  494.     int            *userOptionsArray;
  495.     int            optLen;
  496.     ReturnStatus    sockStatus;
  497.  
  498.     userOptionsArray = (int *)(machCurStatePtr->userState.regState.regs[SP] - 
  499.                        2 * sizeof(int));
  500.     /*
  501.      * OptionsArray is used to give the server the values of "level"
  502.      * and "optName". A buffer ("newBufPtr") is needed to get the option
  503.      * value and the length of the value.
  504.      */
  505.     optionsArray[0] = level;
  506.     optionsArray[1] = optName;
  507.     status = Vm_CopyOut(2 * sizeof(int), (Address)optionsArray, 
  508.             (Address)userOptionsArray);
  509.     if (status != SUCCESS) {
  510.     return(status);
  511.     }
  512.     status = Vm_CopyIn(sizeof(int), (Address)optLenPtr, (Address)&optLen);
  513.     if (status != SUCCESS) {
  514.     return(status);
  515.     }
  516.  
  517.     status = Fs_IOControlStub(socketID, IOC_NET_GET_OPTION,
  518.             sizeof(optionsArray), (Address) userOptionsArray, 
  519.             optLen, (Address) optVal);
  520.  
  521.     if (status != SUCCESS) {
  522.     DebugMsg(status, "getsockopt");
  523.     return(status);
  524.     }
  525.  
  526.     if (optName == SO_ERROR) {
  527.     /*
  528.      * The error value is a Sprite ReturnStatus so we must convert it
  529.      * to the equivalent Unix value.
  530.      */
  531.     (void)Vm_CopyIn(sizeof(int), (Address)optVal, (Address)&sockStatus);
  532.     sockStatus = Compat_MapCode(sockStatus);
  533.     (void)Vm_CopyOut(sizeof(int), (Address)&sockStatus, (Address)optVal);
  534.     }
  535.  
  536.     return(SUCCESS);
  537. }
  538.  
  539. /*
  540.  *----------------------------------------------------------------------
  541.  *
  542.  * setsockopt --
  543.  *
  544.  *    Set the value for a socket option.
  545.  *
  546.  * Results:
  547.  *    If 0        - Successful.
  548.  *    If UNIX_ERROR, then errno = 
  549.  *    EFAULT        - Invalid argument to the ioctl.
  550.  *
  551.  * Side effects:
  552.  *    None.
  553.  *
  554.  *----------------------------------------------------------------------
  555.  */
  556.  
  557. /*VARARGS  (makes lint happy) */
  558. ReturnStatus
  559. MachUNIXSetSockOpt(socketID, level, optName, optVal, optLen)
  560.     int        socketID;    /* Stream ID of socket to set options on. */
  561.     int        level;        /* Socket or protocol level to get the option.*/
  562.     int        optName;    /* Type of option to get. */
  563.     char    *optVal;    /* Address of buffer to store the result. */
  564.     int        optLen;        /* Size of *optVal. */
  565. {
  566.     ReturnStatus    status;
  567.     int            *newBufPtr;
  568.     int            *kernBufPtr;
  569.  
  570.     /*
  571.      * To pass the level, the type of option and the option value to the
  572.      * server, we allocate a new buffer and put the level and type in the
  573.      * first 2 slots and then copy the value to the rest of the buffer.
  574.      */
  575.     newBufPtr = (int *) (machCurStatePtr->userState.regState.regs[SP] -
  576.              (2 * sizeof(int) + optLen));
  577.     kernBufPtr = (int *)malloc(2 * sizeof(int) + optLen);
  578.  
  579.     kernBufPtr[0] = level;
  580.     kernBufPtr[1] = optName;
  581.     status = Vm_CopyIn(optLen, (Address)optVal, (Address)&kernBufPtr[2]);
  582.     if (status != SUCCESS) {
  583.     free((Address)kernBufPtr);
  584.     return(status);
  585.     }
  586.     status = Vm_CopyOut(2 * sizeof(int) + optLen, (Address)kernBufPtr,
  587.             (Address)newBufPtr);
  588.     if (status != SUCCESS) {
  589.     free((Address)kernBufPtr);
  590.     return(status);
  591.     }
  592.  
  593.     status = Fs_IOControlStub(socketID, IOC_NET_SET_OPTION,
  594.                   2 * sizeof(int) + optLen, (Address)newBufPtr,
  595.                   0, (Address) NULL);
  596.  
  597.     free((Address)kernBufPtr);
  598.  
  599.     if (status != SUCCESS) {
  600.     DebugMsg(status, "getsockopt");
  601.     }
  602.     return(status);
  603. }
  604.  
  605. /*
  606.  *----------------------------------------------------------------------
  607.  *
  608.  * listen --
  609.  *
  610.  *    Allows a stream socket to accept remote connection requests and to
  611.  *    specify how many such requests will be queued up before they 
  612.  *    are refused.
  613.  *
  614.  * Results:
  615.  *    If 0        - Successful.
  616.  *    If UNIX_ERROR, then errno = 
  617.  *    EOPNOTSUPP    - The socket type doesn't allow a listen operation.
  618.  *    EFAULT        - Invalid argument to the ioctl.
  619.  *
  620.  * Side effects:
  621.  *    None.
  622.  *
  623.  *----------------------------------------------------------------------
  624.  */
  625.  
  626. ReturnStatus
  627. MachUNIXListen(socketID, backlog)
  628.     int    socketID;    /* Stream ID of socket to be put in listen mode. */
  629.     int    backlog;    /* How many connection requests to queue. */
  630. {
  631.     ReturnStatus    status;
  632.     int            *backLogPtr;
  633.  
  634.     backLogPtr = (int *)(machCurStatePtr->userState.regState.regs[SP] - 4);
  635.     status = Vm_CopyOut(sizeof(int), (Address)&backlog, (Address)backLogPtr);
  636.     if (status != SUCCESS) {
  637.     return(status);
  638.     }
  639.     status = Fs_IOControlStub(socketID, IOC_NET_LISTEN,
  640.             sizeof(backlog), (Address)backLogPtr,
  641.             0, (Address) NULL);
  642.     if (status != SUCCESS) {
  643.     DebugMsg(status, "listen");
  644.     }
  645.     return(status);
  646. }
  647.  
  648. /*
  649.  *----------------------------------------------------------------------
  650.  *
  651.  * recv --
  652.  *
  653.  *    Read data from a connected socket. 
  654.  *
  655.  * Results:
  656.  *    See recvfrom().
  657.  *
  658.  * Side effects:
  659.  *    None.
  660.  *
  661.  *----------------------------------------------------------------------
  662.  */
  663.  
  664. ReturnStatus
  665. MachUNIXRecv(socketID, bufPtr, bufSize, flags)
  666.     int        socketID;
  667.     char    *bufPtr;    /* Address of buffer to place the data in. */
  668.     int        bufSize;    /* Size of *bufPtr. */
  669.     int        flags;        /* Type of operatrion: OR of MSG_OOB, MSG_PEEK*/
  670. {
  671.     return(MachUNIXRecvFrom(socketID, bufPtr, bufSize, flags, 
  672.                 (struct sockaddr *) NULL, (int *) NULL));
  673. }
  674.  
  675. /*
  676.  *----------------------------------------------------------------------
  677.  *
  678.  * recvfrom --
  679.  *
  680.  *    Read data from a socket.
  681.  *
  682.  * Results:
  683.  *    If 0        - Successful.
  684.  *    If UNIX_ERROR, then errno = 
  685.  *    EINVAL        - Bad size or address for senderPtr, senderLenPtr.
  686.  *    EWOULDBLOCK    - If non-blocking, no data are available.
  687.  *    EFAULT        - Invalid argument to the ioctl.
  688.  *
  689.  * Side effects:
  690.  *    None.
  691.  *
  692.  *----------------------------------------------------------------------
  693.  */
  694.  
  695. ReturnStatus
  696. MachUNIXRecvFrom(socketID, bufPtr, bufSize, flags, senderPtr, 
  697.          senderLenPtr)
  698.     int            socketID;    /* Socket to read. */
  699.     char        *bufPtr;    /* Buffer to place the data in. */
  700.     int            bufSize;    /* Size of *bufPtr. */
  701.     int            flags;        /* Type of operatrion: OR of 
  702.                      *  MSG_OOB, MSG_PEEK*/
  703.     struct sockaddr    *senderPtr;    /* Address of sender of the data. */
  704.     int            *senderLenPtr;    /* Size of *senderPtr. (in/out) */
  705. {
  706.     ReturnStatus    status;
  707.     int            *intPtr;
  708.     int            senderLen;
  709.  
  710.     intPtr = (int *)(machCurStatePtr->userState.regState.regs[SP] - 4);
  711.     if (senderPtr != (struct sockaddr *) NULL) {
  712.     if (senderLenPtr == (int *) NULL) {
  713.         return(SYS_INVALID_ARG);
  714.     }
  715.     status = Vm_CopyIn(sizeof(int), (Address)senderLenPtr,
  716.                (Address)&senderLen);
  717.     if (status != SUCCESS) {
  718.         return(status);
  719.     }
  720.     if (senderLen != sizeof(struct sockaddr_in)) {
  721.         return(SYS_INVALID_ARG);
  722.     }
  723.     }
  724.  
  725.     /*
  726.      * If there are flags, ship them to the server.
  727.      */
  728.     if (flags != 0) {
  729.     status = Vm_CopyOut(sizeof(flags), (Address)&flags, (Address)intPtr);
  730.     if (status != SUCCESS) {
  731.         return(status);
  732.     }
  733.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FLAGS,
  734.                   sizeof(flags), (Address)intPtr,
  735.                   0, (Address) NULL);
  736.     if (status != SUCCESS) {
  737.         DebugMsg(status, "recvfrom (ioctl recv_flags)");
  738.         return(status);
  739.     }
  740.     }
  741.  
  742.     status = Fs_ReadStub(socketID, bufSize, bufPtr, intPtr);
  743.     if (status != SUCCESS) {
  744.     DebugMsg(status, "recvfrom (read)");
  745.     return(status);
  746.     }
  747.     (void)Vm_CopyIn(sizeof(int), (Address)intPtr,
  748.            (Address)&machCurStatePtr->userState.unixRetVal);
  749.  
  750.     /*
  751.      * If the caller wants the address of the sender, ask the server for it.
  752.      */
  753.     if (senderPtr != (struct sockaddr *) NULL) {
  754.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FROM,
  755.                   0, (Address) NULL,
  756.                   senderLen, (Address) senderPtr);
  757.     if (status != SUCCESS) {
  758.         DebugMsg(status, "recvfrom (ioctl get_remote)");
  759.         return(status);
  760.     }
  761.     }
  762.     return(SUCCESS);
  763. }
  764.  
  765. /*
  766.  *----------------------------------------------------------------------
  767.  *
  768.  * recvmsg --
  769.  *
  770.  *    Read data from a socket using multiple buffers.
  771.  *
  772.  * Results:
  773.  *    If 0        - Successful.
  774.  *    If UNIX_ERROR, then errno = 
  775.  *    EINVAL        - Bad size or address for msg_name, msg_namelen;
  776.  *                I/O vector length too big.
  777.  *    EWOULDBLOCK    - If non-blocking, no data are available.
  778.  *    EFAULT        - Invalid argument to the ioctl, null address 
  779.  *               for msgPtr.
  780.  *
  781.  * Side effects:
  782.  *    None.
  783.  *
  784.  *----------------------------------------------------------------------
  785.  */
  786.  
  787. ReturnStatus
  788. MachUNIXRecvMsg(socketID, msgPtr, flags)
  789.     int            socketID;    /* Sokect to read data from. */
  790.     struct msghdr    *msgPtr;    /* I/O vector of buffers to store the
  791.                      * data. */
  792.     int            flags;        /* Type of operatrion: OR of 
  793.                      *  MSG_OOB, MSG_PEEK*/
  794. {
  795.     ReturnStatus    status;
  796.     struct msghdr    msg;
  797.     int            *intPtr;
  798.  
  799.     if (msgPtr == (struct msghdr *) NULL) {
  800.     return(SYS_ARG_NOACCESS);
  801.     }
  802.     status = Vm_CopyIn(sizeof(msg), (Address)msgPtr, (Address)&msg);
  803.     if (status != SUCCESS) {
  804.     return(status);
  805.     }
  806.  
  807.     if (msg.msg_name != (Address) NULL) {
  808.     if (msg.msg_namelen != sizeof(struct sockaddr_in)) {
  809.         return(SYS_INVALID_ARG);
  810.     }
  811.     }
  812.  
  813.     if (msg.msg_iovlen > MSG_MAXIOVLEN) {
  814.     return(SYS_INVALID_ARG);
  815.     }
  816.  
  817.     intPtr = (int *)(machCurStatePtr->userState.regState.regs[SP] - 4);
  818.     /*
  819.      * If there are flags, ship them to the server.
  820.      */
  821.     if (flags != 0) {
  822.     status = Vm_CopyOut(sizeof(flags), (Address)&flags, (Address)intPtr);
  823.     if (status != SUCCESS) {
  824.         return(status);
  825.     }
  826.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FLAGS,
  827.                 sizeof(flags), (Address)intPtr,
  828.                 0, (Address) NULL);
  829.     if (status != SUCCESS) {
  830.         DebugMsg(status, "recvmsg (ioctl recv_flags)");
  831.         return(status);
  832.     }
  833.     }
  834.     status = MachUNIXReadv(socketID, msg.msg_iov, msg.msg_iovlen);
  835.     if (status != SUCCESS) {
  836.     return(status);
  837.     }
  838.     if (machCurStatePtr->userState.unixRetVal < 0) {
  839.     DebugMsg(errno, "recvmsg (readv)");
  840.     }
  841.     
  842.     /*
  843.      * If the caller wants the address of the sender, ask the server for it.
  844.      */
  845.     if (msg.msg_name != (Address) NULL) {
  846.     status = Fs_IOControlStub(socketID, IOC_NET_RECV_FROM,
  847.             0, (Address) NULL,
  848.             msg.msg_namelen, (Address) msg.msg_name);
  849.     if (status != SUCCESS) {
  850.         DebugMsg(status, "recvmsg (ioctl recv_from)");
  851.         return(status);
  852.     }
  853.     }
  854.  
  855.     return(SUCCESS);
  856. }
  857.  
  858. /*
  859.  *----------------------------------------------------------------------
  860.  *
  861.  * send --
  862.  *
  863.  *    Write data to a connected socket.
  864.  *
  865.  * Results:
  866.  *    See sendto().
  867.  *
  868.  * Side effects:
  869.  *    None.
  870.  *
  871.  *----------------------------------------------------------------------
  872.  */
  873.  
  874. ReturnStatus
  875. MachUNIXSend(socketID, bufPtr, bufSize, flags)
  876.     int        socketID;    /* Socket to send data on. */
  877.     char    *bufPtr;    /* Address of buffer to send. */
  878.     int        bufSize;    /* Size of *bufPtr. */
  879.     int        flags;        /* Type of operatrion: OR of 
  880.                  *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  881. {
  882.     return(MachUNIXSendTo(socketID, bufPtr, bufSize, flags,
  883.               (struct sockaddr *)NULL, 0));
  884. }
  885.  
  886. /*
  887.  *----------------------------------------------------------------------
  888.  *
  889.  * sendto --
  890.  *
  891.  *    Send a message from a socket.
  892.  *
  893.  * Results:
  894.  *    If 0        - Successful.
  895.  *    If UNIX_ERROR, then errno = 
  896.  *    EINVAL        - Bad size or address for destPtr, destLen..
  897.  *    EWOULDBLOCK    - If non-blocking, the server buffers are too
  898.  *              full to accept the data.
  899.  *    EMSGSIZE    - The buffer is too large to be sent in 1 packet.
  900.  *    EFAULT        - Invalid argument to the ioctl.
  901.  *
  902.  * Side effects:
  903.  *    None.
  904.  *
  905.  *----------------------------------------------------------------------
  906.  */
  907.  
  908. ReturnStatus
  909. MachUNIXSendTo(socketID, bufPtr, bufSize, flags, destPtr, destLen)
  910.     int        socketID;    /* Socket to send data on. */
  911.     char    *bufPtr;    /* Address of buffer to send. */
  912.     int        bufSize;    /* Size of *bufPtr. */
  913.     int        flags;        /* Type of operatrion: OR of 
  914.                  *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  915.     struct sockaddr    *destPtr;    /* Destination to send the data to. */
  916.     int            destLen;    /* Size of *destPtr.  */
  917. {
  918.     ReturnStatus    status;
  919.     Address        usp;
  920.     int            *intPtr;
  921.  
  922.     usp = (Address) (machCurStatePtr->userState.regState.regs[SP]);
  923.     usp -= sizeof(int);
  924.     intPtr = (int *)usp;
  925.     /*
  926.      * If either the flags or a destination are given, send them to the server.
  927.      */
  928.     if ((flags != 0) || (destPtr != (struct sockaddr *) NULL)) {
  929.     Net_SendInfo    sendInfo;
  930.     Net_SendInfo    *sendInfoPtr;
  931.  
  932.     usp -= sizeof(Net_SendInfo);
  933.     sendInfoPtr = (Net_SendInfo *)usp;
  934.     if (destPtr != (struct sockaddr *) NULL) {
  935.         if (destLen != sizeof(struct sockaddr_in)) {
  936.         return(SYS_INVALID_ARG);
  937.         }
  938.         sendInfo.addressValid = TRUE;
  939.         status = Vm_CopyIn(sizeof(Net_InetSocketAddr), (Address)destPtr,
  940.               (Address)&sendInfo.address.inet);
  941.         if (status != SUCCESS) {
  942.         return(status);
  943.         }
  944.     } else {
  945.         sendInfo.addressValid = FALSE;
  946.     }
  947.     sendInfo.flags = flags;
  948.     status = Vm_CopyOut(sizeof(sendInfo), (Address)&sendInfo,
  949.                 (Address)sendInfoPtr);
  950.     if (status != SUCCESS) {
  951.         return(status);
  952.     }
  953.  
  954.     status = Fs_IOControlStub(socketID, IOC_NET_SEND_INFO,
  955.             sizeof(sendInfo), (Address)sendInfoPtr,
  956.             0, (Address) NULL);
  957.     if (status != SUCCESS) {
  958.         DebugMsg(status, "sendto (ioctl)");
  959.         return(status);
  960.     }
  961.     }
  962.  
  963.     status = Fs_WriteStub(socketID, bufSize, bufPtr, intPtr);
  964.     if (status != SUCCESS) {
  965.     DebugMsg(status, "sendto (write)");
  966.     return(status);
  967.     }
  968.     (void)Vm_CopyIn(sizeof(int), (Address)intPtr,
  969.             (Address)&machCurStatePtr->userState.unixRetVal);
  970.     return(SUCCESS);
  971. }
  972.  
  973. /*
  974.  *----------------------------------------------------------------------
  975.  *
  976.  * sendmsg --
  977.  *
  978.  *    Send a message from a socket.
  979.  *
  980.  * Results:
  981.  *    If 0        - Successful.
  982.  *    If UNIX_ERROR, then errno = 
  983.  *    EINVAL        - Bad size or address for msg_name, msg_namelen;
  984.  *                I/O vector length too big.
  985.  *    EWOULDBLOCK    - If non-blocking, the server buffers are too full 
  986.  *              accept the data.
  987.  *    EFAULT        - Invalid argument to the ioctl, null address 
  988.  *               for msgPtr.
  989.  *
  990.  * Side effects:
  991.  *    None.
  992.  *
  993.  *----------------------------------------------------------------------
  994.  */
  995.  
  996. ReturnStatus
  997. MachUNIXSendMsg(socketID, msgPtr, flags)
  998.     int            socketID;    /* Socket to send data on. */
  999.     struct msghdr    *msgPtr;    /* I/O vector of buffers containing
  1000.                      * data to send. */
  1001.     int            flags;        /* Type of operatrion: OR of 
  1002.                      *  MSG_OOB, MSG_PEEK, MSG_DONTROUTE. */
  1003. {
  1004.     ReturnStatus    status;
  1005.     struct msghdr    msg;
  1006.  
  1007.     if (msgPtr == (struct msghdr *) NULL) {
  1008.     return(SYS_ARG_NOACCESS);
  1009.     }
  1010.     status = Vm_CopyIn(sizeof(msg), (Address)msgPtr, (Address)&msg);
  1011.     if (status != SUCCESS) {
  1012.     return(status);
  1013.     }
  1014.  
  1015.     if (msg.msg_iovlen > MSG_MAXIOVLEN) {
  1016.     return(SYS_INVALID_ARG);
  1017.     }
  1018.  
  1019.     if ((flags != 0) || (msg.msg_name != (Address) NULL)) {
  1020.     Net_SendInfo    sendInfo;
  1021.     Net_SendInfo    *sendInfoPtr;
  1022.  
  1023.     if (msg.msg_name != (Address) NULL) {
  1024.         if (msg.msg_namelen != sizeof(struct sockaddr_in)) {
  1025.         return(SYS_INVALID_ARG);
  1026.         }
  1027.         sendInfo.addressValid = TRUE;
  1028.         status = Vm_CopyIn(sizeof(Net_InetSocketAddr),
  1029.                    (Address)msg.msg_name,
  1030.                        (Address)&sendInfo.address.inet);
  1031.         if (status != SUCCESS) {
  1032.         return(status);
  1033.         }
  1034.     } else {
  1035.         sendInfo.addressValid = FALSE;
  1036.     }
  1037.     sendInfo.flags = flags;
  1038.     sendInfoPtr = 
  1039.         (Net_SendInfo *) (machCurStatePtr->userState.regState.regs[SP] - 
  1040.                   sizeof(Net_SendInfo));
  1041.     status = Vm_CopyOut(sizeof(sendInfo), (Address)&sendInfo,
  1042.                 (Address)sendInfoPtr);
  1043.     if (status != SUCCESS) {
  1044.         return(status);
  1045.     }
  1046.  
  1047.     status = Fs_IOControlStub(socketID, IOC_NET_SEND_INFO,
  1048.                 sizeof(sendInfo), (Address)sendInfoPtr,
  1049.                 0, (Address) NULL);
  1050.  
  1051.     if (status != SUCCESS) {
  1052.         DebugMsg(status, "sendmsg (ioctl)");
  1053.         return(status);
  1054.     }
  1055.     }
  1056.  
  1057.     status = MachUNIXWritev(socketID, msg.msg_iov, msg.msg_iovlen);
  1058.     if (status != SUCCESS) {
  1059.     DebugMsg(errno, "sendmsg (writev)");
  1060.     }
  1061.     return(status);
  1062. }
  1063.  
  1064. /*
  1065.  *----------------------------------------------------------------------
  1066.  *
  1067.  * socket --
  1068.  *
  1069.  *    Create a socket in the Internet domain.
  1070.  *
  1071.  * Results:
  1072.  *    If > 0, the stream ID of the new socket.
  1073.  *    If UNIX_ERROR, then errno = 
  1074.  *    EINVAL        - "domain" did not specify the Internet domain.
  1075.  *    ?        - Error from Fs_Open, Fs_IOControl.
  1076.  *
  1077.  * Side effects:
  1078.  *    A new stream is created.
  1079.  *
  1080.  *----------------------------------------------------------------------
  1081.  */
  1082.  
  1083. ReturnStatus
  1084. MachUNIXSocket(domain, type, protocol)
  1085.     int    domain;        /* Type of communications domain */
  1086.     int    type;        /* Type of socket: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW. */
  1087.     int    protocol;    /* Specific protocol to use. */
  1088. {
  1089.     ReturnStatus    status;
  1090.     int            streamID;
  1091.     int            *intPtr;
  1092.     extern char        machHostName[];
  1093.  
  1094.     if (domain != PF_INET) {
  1095.     return(SYS_INVALID_ARG);
  1096.     }
  1097.  
  1098.     if (!gotHostName) {
  1099.     gotHostName = TRUE;
  1100. #ifdef notdef
  1101.     strcpy(streamDevice, "/hosts/");
  1102.     strcat(streamDevice, machHostName);
  1103.     strcat(streamDevice, "/netTCP");
  1104.     strcpy(dgramDevice, "/hosts/");
  1105.     strcat(dgramDevice, machHostName);
  1106.     strcat(dgramDevice, "/netUDP");
  1107.     strcpy(rawDevice, "/hosts/");
  1108.     strcat(rawDevice, machHostName);
  1109.     strcat(rawDevice, "/netIP");
  1110. #endif
  1111.     sprintf(streamDevice, INET_STREAM_NAME_FORMAT, machHostName);
  1112.     sprintf(dgramDevice, INET_DGRAM_NAME_FORMAT, machHostName);
  1113.     sprintf(rawDevice, INET_RAW_NAME_FORMAT, machHostName);
  1114.     }
  1115.  
  1116.     intPtr = (int *)(machCurStatePtr->userState.regState.regs[SP] - 4);
  1117.  
  1118.     if (type == SOCK_STREAM) {
  1119.     status = Fs_OpenStub(streamDevice, FS_READ|FS_WRITE, 0666, intPtr);
  1120.     if (status != SUCCESS) {
  1121.         DebugMsg(status, "socket (stream)");
  1122.         return(status);
  1123.     }
  1124.     } else if (type == SOCK_DGRAM) {
  1125.     status = Fs_OpenStub(dgramDevice, FS_READ|FS_WRITE, 0666, intPtr);
  1126.     if (status != SUCCESS) {
  1127.         DebugMsg(status, "socket (datagram)");
  1128.         return(status);
  1129.     }
  1130.     } else if (type == SOCK_RAW) {
  1131.     status = Fs_OpenStub(rawDevice, FS_READ|FS_WRITE, 0666, intPtr);
  1132.     if (status != SUCCESS) {
  1133.         DebugMsg(status, "socket (raw)");
  1134.         return(status);
  1135.     }
  1136.     } else {
  1137.     return(SYS_INVALID_ARG);
  1138.     }
  1139.     (void)Vm_CopyIn(sizeof(int), (Address)intPtr, (Address)&streamID);
  1140.  
  1141.     if (protocol != 0) {
  1142.     (void)Vm_CopyOut(sizeof(int), (Address)&protocol, (Address)intPtr);
  1143.     status = Fs_IOControlStub(streamID, IOC_NET_SET_PROTOCOL,
  1144.                 sizeof(protocol), (Address)intPtr,
  1145.                 0, (Address) NULL);
  1146.     if (status != SUCCESS) {
  1147.         DebugMsg(status, "socket (ioctl)");
  1148.         return(status);
  1149.     }
  1150.     }
  1151.  
  1152.     machCurStatePtr->userState.unixRetVal = streamID;
  1153.     return(SUCCESS);
  1154. }
  1155.  
  1156. /*
  1157.  *----------------------------------------------------------------------
  1158.  *
  1159.  * shutdown --
  1160.  *
  1161.  *    Shut down part of a full-duplex connection.
  1162.  *
  1163.  * Results:
  1164.  *    0        - The action was successful.
  1165.  *
  1166.  * Side effects:
  1167.  *    None.
  1168.  *
  1169.  *----------------------------------------------------------------------
  1170.  */
  1171.  
  1172. ReturnStatus
  1173. MachUNIXShutdown(socketID, action)
  1174.     int        socketID;    /* Socket to shut down. */
  1175.     int        action;        /* 0 -> disallow further recvs, 
  1176.                  * 1 -> disallow further sends,
  1177.                  * 2 -> combination of above. */
  1178. {
  1179.     ReturnStatus    status;
  1180.     int            *intPtr;
  1181.  
  1182.     intPtr = (int *)(machCurStatePtr->userState.regState.regs[SP] - 4);
  1183.     status = Vm_CopyOut(sizeof(int), (Address)&action, (Address)intPtr);
  1184.     if (status != SUCCESS) {
  1185.     return(status);
  1186.     }
  1187.     status = Fs_IOControlStub(socketID, IOC_NET_SHUTDOWN, 
  1188.             sizeof(action), (Address)intPtr,
  1189.             0, (Address) NULL);
  1190.  
  1191.     if (status != SUCCESS) {
  1192.     DebugMsg(status, "shutdown");
  1193.     }
  1194.     return(status);
  1195. }
  1196.  
  1197. #if 0
  1198.  
  1199. /*
  1200.  *----------------------------------------------------------------------
  1201.  *
  1202.  * Wait --
  1203.  *
  1204.  *    Wait for the Inet server to indicate that a socket is ready
  1205.  *    for some action.
  1206.  *
  1207.  * Results:
  1208.  *    SUCCESS, or FS_TIMEOUT if a timeout occurred.
  1209.  *
  1210.  * Side effects:
  1211.  *    None.
  1212.  *
  1213.  *----------------------------------------------------------------------
  1214.  */
  1215.  
  1216. static ReturnStatus
  1217. Wait(socketID, readSelect, timeOutPtr)
  1218.     int     socketID;    /* Socket to wait on. */
  1219.     Boolean    readSelect;    /* If TRUE, select for reading, else select for
  1220.                  *  writing. */
  1221.     Time    *timeOutPtr;    /* Timeout to use for select. */
  1222. {
  1223.     ReturnStatus    status;
  1224.     int            numReady;
  1225.     Address        usp;
  1226.     int            *numReadyPtr;
  1227.     int            *userMaskPtr;
  1228.     Time        *userTimeOutPtr;
  1229.  
  1230.     usp = (Address)machCurStatePtr->userState.regState.regs[SP];
  1231.     usp -= sizeof(int);
  1232.     numReadyPtr = (int *)usp;
  1233.  
  1234.     if (timeOutPtr == (Time *)NULL) {
  1235.     userTimeOutPtr = (Time *)NULL;
  1236.     } else {
  1237.     usp -= sizeof(Time);
  1238.     userTimeOutPtr = (Time *)usp;
  1239.     status = Vm_CopyOut(sizeof(Time), (Address)timeOutPtr, 
  1240.                 (Address)userTimeOutPtr);
  1241.     if (status != SUCCESS) {
  1242.         return(status);
  1243.     }
  1244.     }
  1245.     /*
  1246.      * Wait until the Inet server indicates the socket is ready.
  1247.      */
  1248.  
  1249.     if (socketID < 32) {
  1250.     int    mask;
  1251.  
  1252.     usp -= sizeof(int);
  1253.     userMaskPtr = (int *)usp;
  1254.     mask = 1 << socketID;
  1255.     status = Vm_CopyOut(sizeof(int), (Address)&mask, (Address)userMaskPtr);
  1256.     if (status != SUCCESS) {
  1257.         return(status);
  1258.     }
  1259.     if (readSelect) {
  1260.         status = Fs_SelectStub(socketID, userTimeOutPtr, userMaskPtr,
  1261.                 (int *) NULL, (int *) NULL, numReadyPtr);
  1262.     } else {
  1263.         status = Fs_SelectStub(socketID, userTimeOutPtr, (int *) NULL, 
  1264.                 userMaskPtr, (int *) NULL, numReadyPtr);
  1265.     }
  1266.     } else {
  1267.     int    *maskPtr;
  1268.     int    numBytes;
  1269.  
  1270.     Bit_Alloc(socketID, maskPtr);
  1271.     Bit_Set(socketID, maskPtr);
  1272.     numBytes = Bit_NumBytes(socketID);
  1273.     usp -= numBytes;
  1274.     userMaskPtr = (int *)usp;
  1275.     status = Vm_CopyOut(numBytes, (Address)maskPtr, (Address)userMaskPtr);
  1276.     if (status != SUCCESS) {
  1277.         return(status);
  1278.     }
  1279.  
  1280.     if (readSelect) {
  1281.         status = Fs_SelectStub(socketID, userTimeOutPtr, userMaskPtr, 
  1282.                 (int *) NULL, (int *) NULL, numReadyPtr);
  1283.     } else {
  1284.         status = Fs_SelectStub(socketID, userTimeOutPtr, (int *) NULL,
  1285.                 userMaskPtr, (int *) NULL, numReadyPtr);
  1286.     }
  1287.     free((char *) maskPtr);
  1288.     }
  1289.  
  1290.     if (status == FS_TIMEOUT) {
  1291.     return(status);
  1292.     } else if (status != SUCCESS) {
  1293.     printf("Wait (socket.c): Fs_Select failed.\n");
  1294.     }
  1295.  
  1296.     (void)Vm_CopyIn(sizeof(int), (Address)numReadyPtr, (Address)&numReady);
  1297.     if (numReady != 1) {
  1298.     printf("Wait (socket.c): Fs_Select returned %d ready\n",
  1299.                 numReady);
  1300.     }
  1301.  
  1302.     return(SUCCESS);
  1303. }
  1304. #endif
  1305.